#include "stdafx.h"
#include "CppUnitTest.h"
#include <HSModel/Human.h>
#include <HSModel/Balloon.h>
#include <HSModel/WorldInfoController.h>
#include <HSModel/Ground.h>
#include <HSModel/SharedConstants.h>

#include <HSModel/Model3DStorage.h>
#include <HSModel/World.h>
#include <HSModel/GameController.h>
#include <HSModel/WorldUpdater.h>

#include <memory>

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace HSModelTests
  {
  TEST_CLASS(BalloonTests)
    {
    public:
      TEST_METHOD(ShouldCreateBlueBalloon)
        {
        World world(HeightMap(1,1));

        Balloon balloon(world, EBalloonColor::BC_BLUE, TVector3(0, 0, 0));
        Assert::AreEqual(std::string("BLUE_BALLOON_0"), balloon.GetType());
        }

      TEST_METHOD(ShouldBeTheSameAngleWithHuman)
        {
        World world(HeightMap(1,1));

        std::map<std::string, IRenderable*> objects;
        HeightMap height_map = HeightMap(GroundConstants::CELL_COUNT + 1, GroundConstants::CELL_COUNT + 1);
        GeneratedHeightMapWithDiamondSquare(height_map, GroundConstants::PLAINS_PERCENTAGE, GroundConstants::MAX_HEIGHT);
        Ground ground(height_map, GroundConstants::CELL_SIZE, GroundConstants::WATER_LEVEL);
        WorldInfoController info(ground, objects);
        Human human(world, HT_DEFAULT_HUMAN, TVector3(0, 1, 0), info);

        Balloon balloon(world, EBalloonColor::BC_BLUE, TVector3(10, 20, 6), &human);
        Assert::AreEqual(balloon.GetAngleAroundY(), human.GetAngleAroundY());
        }

      TEST_METHOD(ShouldHaveCorrectPositionWithHuman)
        {
        World world(HeightMap(1,1));

        std::map<std::string, IRenderable*> objects;
        HeightMap height_map = HeightMap(GroundConstants::CELL_COUNT + 1, GroundConstants::CELL_COUNT + 1);
        GeneratedHeightMapWithDiamondSquare(height_map, GroundConstants::PLAINS_PERCENTAGE, GroundConstants::MAX_HEIGHT);
        Ground ground(height_map, GroundConstants::CELL_SIZE, GroundConstants::WATER_LEVEL);
        WorldInfoController info(ground, objects);
        Human human(world, HT_DEFAULT_HUMAN, TVector3(0, 1, 0), info);

        Balloon balloon(world, EBalloonColor::BC_YELLOW, TVector3(1, 2, 6), &human);
        Assert::AreEqual(1.0, balloon.GetPosition().X());
        Assert::AreEqual(3.0, balloon.GetPosition().Y());
        Assert::AreEqual(6.0, balloon.GetPosition().Z());
        }

      TEST_METHOD(ShouldMoveBalloonWithHumanMove)
        {
        World world;
        GameController game_controller;
        WorldUpdater world_updater(world, game_controller);

        world.AddHuman(TVector3(2, 5, 7), EBalloonColor::BC_BLUE);
        auto humans = world.GetItems<Human>();

        std::vector<std::string> moved_objects;
        world.SubscribeOnMoveEvent([&moved_objects](EventArguments e)
          {
          moved_objects.push_back(e.GetString());
          });
        world_updater.MoveObjects();

        Assert::IsTrue(moved_objects.end() != std::find(moved_objects.begin(), moved_objects.end(), humans[0]->GetName()));
        Assert::IsTrue(moved_objects.end() != std::find(moved_objects.begin(), moved_objects.end(), humans[0]->GetBalloon()->GetName()));
        }

      TEST_METHOD(ShouldChangeStateOnAnimationProperly)
        {
        World world(HeightMap(1,1));

        Balloon balloon(world, EBalloonColor::BC_BLUE, TVector3(0, 0, 0));

        Assert::AreEqual(std::string("BLUE_BALLOON_0"), balloon.GetType());

        balloon.NextFrame();
        Assert::AreEqual(std::string("BLUE_BALLOON_1"), balloon.GetType());

        balloon.NextFrame();
        Assert::AreEqual(std::string("BLUE_BALLOON_0"), balloon.GetType());
        }
    };
  }